package com.yoso.shop.infrastructure.proxy.entity;

import com.yoso.base.infrastructure.exception.BaseException;
import com.yoso.base.interfaces.controller.BaseResponse;
import com.yoso.shop.infrastructure.constants.error.SqlErrorConstants;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import java.sql.SQLIntegrityConstraintViolationException;

/**
 * @author shizejin
 * @date 2021/11/30
 * @description: 代理controller的insert的方法，检查是否违反唯一索引
 */
@Component
@Aspect
@Slf4j
public class EntityAspect {

    @Pointcut("execution( * com.yoso.shop..*.save*(..))")
    public void entityInsert() {
    }

    @Around("entityInsert()")
    public Object around(ProceedingJoinPoint jp) {
        Object result = null;
        try {
            result = jp.proceed();
        } catch (Throwable throwable) {
            Throwable cause = throwable.getCause();
            if (cause instanceof SQLIntegrityConstraintViolationException) {
                //错误信息
                String errMsg = cause.getMessage();
                //根据约束名称定位是那个字段
                if (StringUtils.isNotBlank(errMsg)) {
                    if (errMsg.contains(SqlErrorConstants.DUPLICATE_ENTRY)) {

                        result = BaseResponse.error("重复数据！" + errMsg);
                        log.error("数据重复!\t" + errMsg);

//                         有异常必须抛出，否则事务不会回滚
                        throw new BaseException("重复数据！" + errMsg);
                    }
                    if (errMsg.contains(SqlErrorConstants.CANNOT_BE_NULL)) {
                        result = BaseResponse.error("字段不能为空！" + errMsg);
                        log.error("字段不能为空！\t" + errMsg);
                        throw new BaseException("字段不能为空！\t" + errMsg);
                    }
                }
            } else {
                throwable.printStackTrace();
            }
        }
        return result;

    }
}
